在上一篇文章中,我們學會了如何使用 JSON.stringify() 將陣列轉為字串並寫入 LocalStorage。但是,光是會把資料「存進去」還不夠;當使用者第二天重新打開網站時,我們必須能在網頁載入的第一時間,將這些字串「抓出來」並還原成可操作的 JavaScript 物件陣列。
此外,當使用者想要重新開始、或是資料累積過多時,我們也必須提供一個安全且具備防呆確認的「一鍵清空」機制。
今天作為 LocalStorage 系列的下集,我們將重點放在 JSON.parse() 反序列化讀取、預設空陣列容錯,以及 雙重確認(Confirm)的一鍵清空功能。
在撰寫程式碼之前,我們先來拆解初始化與資料銷毀這兩個關鍵階段的設計思維:
當網頁準備就緒時,程式必須主動執行以下步驟:
localStorage.getItem("key") 從瀏覽器拉取資料。getItem 回傳 null),必須透過邏輯或運算子 || [] 自動降級為空陣列,防止 JSON.parse(null) 後續引發TypeError。renderTimers() 將恢復後的陣列轉化為 DOM 節點。「清空」屬於破壞性操作(Destructive Action),為了避免使用者誤觸造成資料無法挽回的遺憾,必須建立兩道防線:
confirm() 跳出警示視窗,明確告知「此動作無法復原」,只有使用者按下確定後才執行資料抹除。我們在 /tool4-timer.js 與 /tool3-schedule.js 中實現資料讀取、空狀態渲染與清空事件監聽:
/tool4-timer.js
// 1. 初始化:從 LocalStorage 載入歷史紀錄
let timerItems = JSON.parse(localStorage.getItem("med_timer_list")) || [];
renderTimers();
// 3. 一鍵清空事件
if (btnClearTimers) {
btnClearTimers.addEventListener("click", () => {
if (timerItems.length === 0) {
alert("目前沒有任何追蹤中的開瓶項目!");
return;
}
if (confirm("確定要清空所有開瓶倒數追蹤紀錄嗎?此動作無法復原!")) {
timerItems = [];
saveAndRender();
}
});
}
function renderTimers(){
timerList.innerHTML = "";
if (timerItems.length === 0) {
timerList.innerHTML = `<p style="color: var(--text-muted); font-size: 0.9rem; text-align: center; padding: 20px 0;">目前尚無追蹤中的開瓶藥品</p>`;
return;
}
// ...渲染節點邏輯
}
/tool3-schedule.js
// 4. 新增:一鍵清空事件
if (btnClearSchedule) {
btnClearSchedule.addEventListener("click", () => {
if (medList.length === 0) {
alert("目前時間表中沒有任何項目!");
return;
}
if (confirm("確定要清空用藥時間表中的所有藥品嗎?此動作無法復原!")) {
medList = [];
saveAndRender();
}
});
}
JSON.parse() 與短路運算子 || [] 的完美搭配JSON.parse(localStorage.getItem("med_timer_list")) || [] 是非常經典的 JS 防禦性寫法。
當 key 值不存在時,getItem() 會回傳 null。在 JavaScript 中 JSON.parse(null) 結果雖然是 null,但 null屬於 Falsy 值,這時短路運算子 || 就會發揮作用,自動將變數初始化為空陣列 []。這確保了 timerItems 與 medList 永遠都是合法且可進行 .push() 或 .length 操作的陣列物件!
在點擊清空按鈕時,我們第一時間進行長度檢查:if (timerItems.length === 0) { alert(...); return; }
如果畫面上本來就沒有資料,就不應該跳出令人困惑的「確定要清空嗎」詢問視窗,而是直接提示無資料可清空並終斷執行(return),減少不必要的視覺干擾。
confirm() 破壞性操作警示使用 confirm("此動作無法復原!") 建立第二道對話框防線。只有當使用者明確點擊「確定」回傳 true 時,才會將記憶體中的陣列歸零(timerItems = []),隨後呼叫 saveAndRender() 一併更新 LocalStorage 與畫面。
當陣列被清空或剛好無任何項目時,renderTimers() 透過條件分支輸出帶有 --text-muted 的預設提示字串。這屬於重要卻常被忽略的 UI/UX 細節——避免留下一片空白的容器,讓使用者以為網頁發生錯誤或當機。
今天我們成功透過 JSON.parse() 實現了開頁時的歷史紀錄反序列化復原,並搭配安全確認機制完成了一鍵清空功能,正式讓 [Tool 3] 與 [Tool 4] 擁有了完整且穩健的 LocalStorage 資料生命週期管理。
在明天的 [Day 28] 中,我們將展開全站最終的收尾工作:[全站 RWD 響應式優化與跨裝置視覺校正],針對手機、平板與桌機進行排版微調,確保這套醫療輔助工具在各種裝置上都能呈現最完美的質感。鐵人賽最後倒數 3 天,我們明天見!